<template>
  <view class="progress-container">
    <canvas
      ref="refChart"
      :canvas-id="canvasId"
      :style="{
        width: `${props.size}rpx`,
        height: `${props.size}rpx`
      }"
      class="progress-canvas"
    />
  </view>
</template>

<script setup>
const props = defineProps({
  // 当前进度 (0-100)
  value: {
    type: Number,
    default: 0
  },
  // 尺寸(rpx)
  size: {
    type: Number,
    default: 148
  },
  // 进度条宽度(rpx)
  strokeWidth: {
    type: Number,
    default: 6
  },
  // 进度条长度(rpx)
  strokeLength: {
    type: Number,
    default: 10
  },
  // 进度条颜色
  color: {
    type: String,
    default: '#27be87'
  },
  // 背景颜色
  backgroundColor: {
    type: String,
    default: '#DFE2E8'
  },
  // 是否显示进度文本
  showText: {
    type: Boolean,
    default: true
  },
  // 是否显示进副文本
  showSubText: {
    type: Boolean,
    default: true
  },
  title: {
    type: String,
    default: ''
  },
  subTitle: {
    type: String,
    default: ''
  }
})

const refChart = ref(null)
const canvasId = ref('progressCanvas_' + Date.now())
let ctx = null
let progress = 0
const timer = ref(null)
// props参数数值转为px
const size = g_utils.rpxToPx(props.size)

const strokeWidth = g_utils.rpxToPx(props.strokeWidth)
const strokeLength = g_utils.rpxToPx(props.strokeLength)
// canvas参数
const center = size / 2
const radius = center
const totalTickCount = 40 //多少个刻度
// 定义顺时针方向的角度范围（从右侧开始）
const startAngle = -Math.PI / 2 // 12点钟方向
const endAngle = -Math.PI / 2 + (Math.PI / 2) * 4 // 12点钟方向
// 修改：逆时针计算进度角度
const rangeAngle = -(endAngle - startAngle)
const getTickCount = count => Math.round((count / 100) * totalTickCount) // 获取刻度数量
let curTickCount = getTickCount(progress) // 当前刻度数量
const cRingMargin = g_utils.rpxToPx(10) // 圆环外边距

watch(
  () => props.value,
  nv => {
    if (timer.value) {
      clearInterval(timer.value)
      timer.value = null
    }
    nextTick(() => {
      updateProgress()
    })
  }
)

onMounted(_ => {
  // uni-app中需要通过uni.createCanvasContext获取上下文
  ctx = uni.createCanvasContext(canvasId.value, this)
  initProgress()
  nextTick(() => {
    updateProgress()
  })
})

onBeforeUnmount(_ => {
  if (timer.value) {
    clearInterval(timer.value)
    timer.value = null
  }
})

onUnload(() => {
  if (timer.value) {
    clearInterval(timer.value)
    timer.value = null
  }
})

const updateProgress = _ => {
  // clearInterval(timer.value)
  // 模拟定时器计数
  const DURATION = 1500 // 总时长1.5s
  const STEP_DURATION = 100 // 每步间隔100ms
  const MIN_STEP = 2 // 最小步长

  // 计算合适的步长
  const step = Math.max(props.value / (DURATION / STEP_DURATION), MIN_STEP)
  const totalCount = Math.ceil(props.value / step)

  for (let i = 0; i < totalCount; i++) {
    timer.value = setTimeout(() => {
      progress = Math.min(progress + step, props.value)
      curTickCount = getTickCount(progress)
      initProgress()
    }, i * STEP_DURATION)
  }
  // 开发过程中定时器有时没有清除
  // timer.value = setInterval(() => {
  //   progress += step
  //   if (progress > props.value) {
  //     progress = props.value
  //     clearInterval(timer.value)
  //   }
  //   curTickCount = getTickCount(progress)
  //   initProgress()
  // }, 50)
}

function resetProgress() {
  progress = 0
  drawProgress()
}

const initProgress = _ => {
  // 清除画布
  ctx.clearRect(0, 0, props.size, props.size)
  drawProgress()
  drawRealProgress()
  drawText()
  // 绘制到画布上
  ctx.draw()
}

const drawProgress = _ => {
  // 绘制中间的圆环
  const cRadius = radius - strokeLength - cRingMargin
  ctx.beginPath()
  ctx.arc(center, center, cRadius, 0, 2 * Math.PI)
  ctx.strokeStyle = props.value > 0 ? props.color : '#DFE2E8'
  ctx.lineWidth = g_utils.rpxToPx(1)
  ctx.stroke()
  // 绘制刻度线
  for (let i = 0; i <= totalTickCount; i++) {
    const angle = startAngle + (rangeAngle * i) / totalTickCount
    const innerRadius = radius - strokeLength
    const outerRadius = radius

    ctx.beginPath()
    ctx.moveTo(
      center + Math.cos(angle) * innerRadius,
      center + Math.sin(angle) * innerRadius
    )
    ctx.lineTo(
      center + Math.cos(angle) * outerRadius,
      center + Math.sin(angle) * outerRadius
    )
    ctx.strokeStyle = props.backgroundColor
    ctx.lineWidth = strokeWidth
    ctx.stroke()
  }
}

const drawRealProgress = _ => {
  // 绘制进度刻度线
  for (let i = 0; i < curTickCount; i++) {
    const angle = startAngle + (rangeAngle * i) / totalTickCount
    const innerRadius = radius - strokeLength
    const outerRadius = radius

    ctx.beginPath()
    ctx.moveTo(
      center + Math.cos(angle) * innerRadius,
      center + Math.sin(angle) * innerRadius
    )
    ctx.lineTo(
      center + Math.cos(angle) * outerRadius,
      center + Math.sin(angle) * outerRadius
    )
    ctx.strokeStyle = props.color
    ctx.lineWidth = strokeWidth
    ctx.stroke()
  }
}

const drawText = _ => {
  // 绘制文本（可选）
  if (props.showText) {
    ctx.beginPath()
    ctx.font = `bold 12px Arial`
    ctx.setFontSize(g_utils.rpxToPx(24))
    ctx.setFillStyle(props.value > 0 ? '#333333' : '#999999')
    ctx.setTextAlign('center')
    ctx.setTextBaseline('middle')
    const textY = props.showSubText ? center - g_utils.rpxToPx(19) : center
    ctx.fillText(props.title, center, textY)
  }

  if (props.showSubText) {
    // 绘制上下文本分界线
    ctx.beginPath()
    const subTextStartX =
      strokeLength + cRingMargin + g_utils.rpxToPx(1) + g_utils.rpxToPx(10)
    ctx.moveTo(subTextStartX, center)
    ctx.lineTo(radius * 2 - subTextStartX, center)
    ctx.strokeStyle = '#DCDCDC'
    ctx.lineWidth = g_utils.rpxToPx(1)
    ctx.stroke()

    ctx.beginPath()
    ctx.font = 'normal 9px Arial'
    ctx.setFontSize(g_utils.rpxToPx(18))
    ctx.setFillStyle('#999')
    ctx.setTextAlign('center')
    ctx.setTextBaseline('middle')
    ctx.fillText(props.subTitle, center, center + g_utils.rpxToPx(16))
  }
}
</script>

<style lang="scss" scoped>
.progress-container {
}
.progress-canvas {
  display: flex;
  justify-content: center;
  align-items: center;
}
</style>
